package com.ease.common.util;

import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

/**
 * 
 * @author nathanleewei
 * 
 */
public abstract class ReflectionUtil {

	// private static final transient Log log =
	// LogFactory.getLog(ReflectionUtil.class);

	// @SuppressWarnings("unchecked")
	public static Class<?> getGenericType(final Class<?> clazz) {
		return getGenericType(clazz, 0);
	}

	public static Class<?> getGenericType(final Class<?> clazz, final int index) {

		Type genericType = clazz.getGenericSuperclass();

		if (!(genericType instanceof ParameterizedType)) {
			// log.warn(clazz.getSimpleName() +
			// "'s superclass not ParameterizedType");

			return Object.class;
		}

		Type[] params = ((ParameterizedType) genericType).getActualTypeArguments();

		if (index >= params.length || index < 0) {
			// log.warn("Index: " + index + ", Size of " + clazz.getSimpleName()
			// + "'s Parameterized Type: " + params.length);
			return Object.class;
		}
		if (!(params[index] instanceof Class)) {
			// log.warn(clazz.getSimpleName() +
			// " not set the actual class on superclass generic parameter");
			return Object.class;
		}

		return (Class<?>) params[index];
	}

	/**
	 * 
	 * @param type
	 * @param i
	 * @return
	 */
	public static Class<?> getClass(Type type, int i) {
		if (type instanceof ParameterizedType) { // 处理泛型类型
			return getGenericClass((ParameterizedType) type, i);
		} else if (type instanceof GenericArrayType) {
			GenericArrayType genericArrayType = (GenericArrayType) type;
			return getClass(genericArrayType.getGenericComponentType(), i);
		} else if (type instanceof TypeVariable) {
			return (Class<?>) getClass(((TypeVariable<?>) type).getBounds()[0], 0); // 处理泛型擦拭对象
		} else {// class本身也是type,强制转型
			return (Class<?>) type;
		}
	}

	/**
	 * 
	 * @param parameterizedType
	 * @param i
	 * @return
	 */
	public static Class<?> getGenericClass(ParameterizedType parameterizedType, int i) {
		Object genericClass = parameterizedType.getActualTypeArguments()[i];
		if (genericClass instanceof ParameterizedType) { // 处理多级泛型
			return (Class<?>) ((ParameterizedType) genericClass).getRawType();
		} else if (genericClass instanceof GenericArrayType) { // 处理数组泛型
			return (Class<?>) ((GenericArrayType) genericClass).getGenericComponentType();
		} else if (genericClass instanceof TypeVariable) { // 处理泛型擦拭对象
			return (Class<?>) getClass(((TypeVariable<?>) genericClass).getBounds()[0], 0);
		} else {
			return (Class<?>) genericClass;
		}
	}
}
